﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Security.Principal;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Security.Permissions;
using System.Security.Cryptography;
using System.IO;
using iTunesLib;
using Project1;



namespace StudyCollections
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            // Semplice array di interi, da usare QUANDO CONOSCO a priori il numero degli elementi
            int[] interi = new int[] {4,5,11};
            // Accesso a un elemeento
            interi[1] = 333;

            // MessageBox.Show(interi.Max().ToString());

           
            // L'arrayList è la piu' semplice delle Collections, è indicizzata, è NON ordinata
            ArrayList infiniti = new ArrayList();

            // con ADD aggiungo sempre in fondo
            infiniti.Add("stringa");
            infiniti.Add(333232);
            infiniti.Add(new Form1());

            // con INSERT aggiungo dove dico io
            infiniti.Insert(0, infiniti.Count);

            // Uso l'indice per accedere a un elemento preciso
            //Console.WriteLine("Elemento 0: " + infiniti[0]);

            Console.WriteLine("Totale elementi: " + infiniti.Count);

            infiniti.RemoveAt(0);

            //Console.WriteLine("Totale elementid dopo canc elemento: " + infiniti.Count);

            //infiniti.Clear();

            //Console.WriteLine("Totale elementid dopo clear " + infiniti.Count);

            // Scorro la mia collection con un Enumerator
  
            IEnumerator enumerator =infiniti.GetEnumerator();

            while (enumerator.MoveNext())
            {
                Console.WriteLine(enumerator.Current.ToString());

            }

        }

        private void button2_Click(object sender, EventArgs e)
        {

            // Per gestire una struttura sequenziale uso le QUEUE, che seguono logica FIFO
            Queue q = new Queue();

            q.Enqueue("primo");
            q.Enqueue("secondo");
            q.Enqueue("terzo");

            while (q.Count > 0)
            {
                string passeggero = (string) q.Dequeue();
                //Console.WriteLine("pass: " + passeggero);
            }

            // Con lo STACK invece lavoso sulla sommità della pila di piatti, posso infatti
            // aggiungere e sottrarre solo l'ultimo elemento, la logica è la LIFO

            Stack s = new Stack();

            s.Push("primo");
            s.Push("secondo");
            s.Push("terzo");

            while (s.Count > 0)
            {
                string passeggero = (string)s.Pop();
                Console.WriteLine("pass: " + passeggero);
            }



        }

        private void button3_Click(object sender, EventArgs e)
        {
            // I dizionari sono delle particolari collection formate da coppie di dati
            // ogni coppia è formata da 1 chiave e 1 valore
            // Per ordinare serve chiamare il metodo SORT

            Hashtable table = new Hashtable();

            // Primo metodo per aggiungere elementi
            table.Add("inglese", 8);
            table.Add("francese", 6);
            table.Add("storia", "n/d");

            // Secondo metodo
            table["italiano"] = 5;

            

            // Scorro tutti gli elemeni tramite l'item
            foreach (DictionaryEntry item in table)
            {
                Console.WriteLine("Chiave {0} = {1}", item.Key, item.Value);
            }

            // Ricerca di elemento (solo per chiave)
            Console.WriteLine("Ultimo esame di francese:"  + table["francese"]);

            // Recupero tutti i valori e faccio la media
            ArrayList valori = new ArrayList(table.Values);

            double media = 0;
            int totale = 0;
            
            // Scorro tutti gli elementi
            for (int i = 0; i < valori.Count; i++)
            {
                int val = 0;

                if (int.TryParse(valori[i].ToString(), out val))
                {
                    media += val;
                    totale++;
                }
            }

            // Espongo la media
            if (totale > 0)
                Console.WriteLine("La media e' {0}", (media/totale).ToString());

            table.Clear();
            table = null;
            // E ora proviamo a fare una hastable con Equality personalizzato, che non va distinzione
            // tra minuscole e maiuscolo, il nome è MyEqualityCaseInsensitive
            Hashtable tableCaseInsenstive = new Hashtable(new MyEqualityCaseInsensitive());

            tableCaseInsenstive["INGLESE"] = 8;
            tableCaseInsenstive["Inglese"] = 6;
            // Darà errore in quanto le due stringhe hanno lo stesso hash
            // l'unico modo e creare una nuova classe dove ci saranno in override i metodi
            // GetHashCode() e Equals()

            Console.WriteLine("Totale -> {0}", tableCaseInsenstive.Count);

            foreach (DictionaryEntry entry in tableCaseInsenstive)
                Console.WriteLine("Chiave: {0} = {1}", entry.Key, entry.Value);
            // int code = table["italiano"].GetHashCode();

            


            // E ora mi creo un mio dizionario
            // Ho creato una classe dizionario che implementa IDictionary

            Dizionario mydiz = new Dizionario();
            //mydiz.Add("prova", "prova");



        }

        private void button4_Click(object sender, EventArgs e)
        {
            // Vediamo le sortedlist, dove gli elementi vengono automaticamente ordinati
            // per CHIAVE (non per valore!)

            SortedList listaOrdinata = new SortedList();

            listaOrdinata.Add("Paolo", 50);
            listaOrdinata.Add("Luca", 41);
            listaOrdinata.Add("Anna", 93);
            listaOrdinata.Add("Marco", null);

            // In che posizione e' finita Anna?
            Console.WriteLine("Anna è finita in {0} posizione!" , listaOrdinata.IndexOfKey("Marco"));

            // Chi ha 50 anni? (valore), prima mi becco l'indice
            // poi mi becco il valore in quella posizione
            int indice = (int) listaOrdinata.IndexOfValue(50);
            string nome = listaOrdinata.GetKey(indice).ToString();
            Console.WriteLine("La persona con 50 anni si chiama: " + nome);

            // Altrimenti mi copio tutte le chiavi in una IList
            IList lista = listaOrdinata.GetKeyList();
            Console.WriteLine("La persona con 50 anni si chiama: " + lista[indice]);

            // Vediamo se è vero che ha ordinato tutto
            foreach (DictionaryEntry entry in listaOrdinata)
            {
                Console.WriteLine("Chiave {0} = {1}", entry.Key, entry.Value);
            }

            
        }

        
        private void button5_Click(object sender, EventArgs e)
        {
            // Per il processo di autentitazione uso WindowsIdentity, la classe
            // che memorizza i risultati dell'autenticazione all'accesso a windows
            
            // Posso usare i metodo GetAnoynmous per farmi restituire un utente generico,
            // utile per capire se ho alcuni permessi particolari
            // GetCurrent ritorna l'utente attualmente collegato
            // Impersonate per diventare un altro utente

            WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();

            Console.WriteLine("Autenticazione: " + currentIdentity.AuthenticationType);
            Console.WriteLine("System? " + currentIdentity.IsSystem);
            Console.WriteLine("Autenticated? " + currentIdentity.IsAuthenticated);
            Console.WriteLine("Nome: " + currentIdentity.Name);
            Console.WriteLine("Sid: " + currentIdentity.User);
            Console.WriteLine("Token: " + currentIdentity.Token);

            // La classe per capire a quali membri ha accesso una particolare identità, o faccio cosi o la prelevo dal thread

            WindowsPrincipal currentPrincipal = new WindowsPrincipal(currentIdentity);

            Console.WriteLine("Amministratore? " + currentPrincipal.IsInRole(WindowsBuiltInRole.Administrator).ToString());
            Console.WriteLine("Power User? " + currentPrincipal.IsInRole(WindowsBuiltInRole.PowerUser).ToString());
            Console.WriteLine("User? " + currentPrincipal.IsInRole(WindowsBuiltInRole.User).ToString());

            // Posso anche verificare se ha accesso a un gruppo particolare
            
            Console.WriteLine("Domain accounting? " + currentPrincipal.IsInRole(@"BETA80GROUP\Accounting"));

            
    

        }
        [PrincipalPermission(SecurityAction.Demand, Role = @"BUILTIN\Administrators")]
        private void button6_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Sei un admin!");
        }

        private void button7_Click(object sender, EventArgs e)
        {
            // Per le chiavi simmetriche, l'unica completamente managed e' la Rijndael,
            // altre sono la RC2, la DES e la TripleDES
            
            // Esempio di crypting usando Rijndael, con cifratura AES
            // usando una key generata dall'algoritmo
            string inFileName = @"c:\temp\testo_chiaro.txt";
            string outFileName = @"c:\temp\testo_crypted.txt";
            string keyFileName = @"c:\temp\key.enc";

            // Mi creo i tre stream
            FileStream streamIn = new FileStream(inFileName, FileMode.Open, FileAccess.Read);
            FileStream streamOut = new FileStream(outFileName, FileMode.OpenOrCreate, FileAccess.Write);
            FileStream streamKey = new FileStream(keyFileName, FileMode.OpenOrCreate, FileAccess.Write);
            

            // Mi creo un buffer in base alla grandezza dello STREAM in ingresso
            byte[] fileData = new byte[streamIn.Length];

            // Nel buffer ci ficco il contentuo del mio stream da criptare
            streamIn.Read(fileData, 0, fileData.Length);
            
            //testobyte = encoding.GetBytes(testo);

            // Lo ficco in un memorystream
            //MemoryStream stream = new MemoryStream(testobyte, 0, testobyte.Length);


            // Istanzio la classe
            SymmetricAlgorithm myAes = new RijndaelManaged();
            byte[] mySecretKeyIV = new byte[16] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };

            myAes.IV = mySecretKeyIV;

            myAes.GenerateKey();

            

            byte[] mySecretKey = new byte[myAes.KeySize / 8];
            mySecretKey = myAes.Key;
            streamKey.Write(mySecretKey, 0, mySecretKey.Length);
            streamKey.Close();
            streamKey.Dispose();
            streamKey = null;

            
            // Creo l'encryptor, usando l'istanza del mio algoritmo
            ICryptoTransform encryptor = myAes.CreateEncryptor();

            // Creo finalmente il CryptoStream che si occupera di scrivere nel mio STREAM out
            CryptoStream encryptStream = new CryptoStream(streamOut, encryptor, CryptoStreamMode.Write);
            
            // Riempio il criptostream
            encryptStream.Write(fileData, 0, fileData.Length);

            encryptStream.Close();
            encryptStream.Dispose();
            streamIn.Close();
            streamIn.Dispose();
            streamOut.Close();
            streamOut.Dispose();

            //string keyInChiaro;
            //ASCIIEncoding encoding = new ASCIIEncoding();
            //keyInChiaro = encoding.GetString(mySecretKey);



        }

        private void button8_Click(object sender, EventArgs e)
        {
            // Esempio di decrypting usando Rijndael, con cifratura AES
            // usando una key letto da file
            string inFileName = @"c:\temp\testo_crypted.txt";
            string outFileName = @"c:\temp\testo_decrypted.txt";
            string keyFileName = @"c:\temp\key.enc";

            // Mi creo i due stream
            FileStream streamIn = new FileStream(inFileName, FileMode.Open, FileAccess.Read);
            FileStream streamOut = new FileStream(outFileName, FileMode.OpenOrCreate, FileAccess.Write);
            FileStream streamKey = new FileStream(keyFileName, FileMode.Open, FileAccess.Read);


            // Mi creo un byte array in base alla grandezza dello STREAM in ingresso
            byte[] fileData = new byte[streamIn.Length];

            // Nel buffer ci ficco il contentuo del mio stream criptato: qui stava l'errore !!!!
            // Lo stream viene gia' letto dopo con il CryptoStream!!!!
            //streamIn.Read(fileData, 0, fileData.Length);


            //testobyte = encoding.GetBytes(testo);

            // Lo ficco in un memorystream
            //MemoryStream stream = new MemoryStream(testobyte, 0, testobyte.Length);


            // Istanzio la classe
            SymmetricAlgorithm myAes = new RijndaelManaged();

            // Carico la Key
            byte[] mySecretKey = new byte[streamKey.Length];
            streamKey.Read(mySecretKey, 0, mySecretKey.Length);
            streamKey.Close();
            streamKey.Dispose();
            streamKey = null;

            myAes.Key = mySecretKey;

            byte[] mySecretKeyIV = new byte[16] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };
            myAes.IV = mySecretKeyIV;
            

            // Creo il decryptor, usando l'istanza del mio algoritmo
            ICryptoTransform decryptor = myAes.CreateDecryptor();


            // Creo finalmente il CryptoStream che si occupera di leggere dal STREAM in
            //CryptoStream decryptStream = new CryptoStream(streamOut, decryptor, CryptoStreamMode.Write);

            CryptoStream decryptStream = new CryptoStream(streamIn, decryptor, CryptoStreamMode.Read);


            // Quanto c'e' nello stream?
            byte[] decryptedData = new byte[100];


            // Decritto
            int bytesLetti = decryptStream.Read(decryptedData, 0, decryptedData.Length);


            string testo = Encoding.ASCII.GetString(decryptedData, 0, bytesLetti);

            streamOut.Write(decryptedData, 0, bytesLetti);





            // Riempio il criptostream
            //decryptStream.Write(fileData, 0, fileData.Length);

            decryptStream.Close();
            decryptStream.Dispose();
            streamIn.Close();
            streamIn.Dispose();
            streamOut.Close();
            streamOut.Dispose();

            //string keyInChiaro;
            //ASCIIEncoding encoding = new ASCIIEncoding();
            //keyInChiaro = encoding.GetString(mySecretKey);

        }

        private void button9_Click(object sender, EventArgs e)
        {
            // La crittografia asimmetrica si basa sulla coppia chiaeve pubblica - chiave privata.
            // I messaggi vengono criptati con la chiave pubblica e possono essere decriptati
            // solo con la chiave privata, gia' in possesso del destinatario!
            // Sono implementati RSA e DSA

            // Esempio crezione chiave RSA

            // Creo un CSPParameter per poter memorizzare la chiave nel CSP in modo permanente

            CspParameters csp = new CspParameters();
            csp.KeyContainerName = "RSAExample";

            // Creo istanza classe algoritmo RSA
            RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider(csp);

            // La salviamo in modo persistente, in modo tale che non cambiera' piu'
            myRSA.PersistKeyInCsp = true;

            // Creo un nuovo RSA Parameter
            RSAParameters allRSAKey = myRSA.ExportParameters(true);

            //string rsaString = myRSA.ToXmlString(false);

            //string rsaFile = @"c:\temp\rsaPublic.xml";
            //File.WriteAllText(rsaFile, rsaString, Encoding.UTF8);

            string rsaStringPK = myRSA.ToXmlString(true);
            string rsaFilePK = @"c:\temp\rsaPK.xml";

            File.WriteAllText(rsaFilePK, rsaStringPK, Encoding.UTF8);

            foreach (byte thisByte in allRSAKey.D)
                Console.WriteLine(thisByte.ToString("X2") + " ");


            //<RSAKeyValue>
            //    <Modulus>wDwElB2GdNiL3mwrpJ158UqbKiDLCdJNx94SjWWuvNXRjTa/fNsm5Ik0lzLnkfxDNa+OIUlhLxWIin4aTED3rkIBQinDDRYSrSAb4lR+LZwADIyqhBAIwfJiSl8UXwKorBm/eFtC5S6ryiJG005gGfVPjOBQ+BywDmcske2Uwrk=</Modulus>
            //    <Exponent>AQAB</Exponent>
            //    <P>/fQYGfVQhf5MSiBIqHkd40Kk/WP7DfUyhNRb8TkhZz+DRuYiE+wZPqkKXtbIiKqu0zlQ0KjihZKCW9boqKhbAQ==</P>
            //    <Q>wciY7rF6fSPwDxstCYHpylk4OxACk3ofepaVi6nsH5d2w8gN5y+96Ze+YeSNUFRfydFNoaF78xCi4Ttp0kX/uQ==</Q>
            //    <DP>nbUHfp9cmUm6INJ5rL5CdE5/3ahIUXuzGtAyJNSgzNihctcZ1JtrdgFOImVp9Y1hsmTGrj4jJmY8tEH7DDo5AQ==</DP>
            //    <DQ>dzMmZ4VCfGGz1Ab6cCO6pN62yRXzD7aKUIT6XlvaxCAOTSXs722dm2fdEyhciLIt7d3Sq/7CWOS93GAImvC1+Q==</DQ>
            //    <InverseQ>87RuTcFB2ZTLaa80E+hD64mSo3uPmGlI2Iipo4ZWCLorPSBgbof58KAJ+IlA0xFnAkdXj3mEFBe1E1hb4RTnYA==</InverseQ>
            //    <D>OrAYFcAN1I5n5TfQ+yi4mdnVFT99vTnfVS2PLGvmtO/yUdJtE4k0joD09VQtLnx9aF54XeExMla4oM9u5+jNtHTwyf35ypJNpaCR05ipwWLOY0SqgNAzN+JNcW1c8SuEEYBYHmh8g+Oht4I4O80iG3yPTtt4WF+lMWoRKV2vQAE=</D>
            //</RSAKeyValue>

            // E ora criptiamo un messaggio
            string messaggioRSAinChiaro = "vediamo come cripta questo RSA";

            // Trasformiamo in un array di bytes
            byte[] msgToCript = Encoding.ASCII.GetBytes(messaggioRSAinChiaro);
            byte[] msgCripted = myRSA.Encrypt(msgToCript, false);

            Console.WriteLine("Messaggio in chiaro: " +  messaggioRSAinChiaro);
            Console.WriteLine("Messaggio criptato: " + Encoding.ASCII.GetString(msgCripted));


            byte[] msgDeCripted = myRSA.Decrypt(msgCripted, false);

            Console.WriteLine("Messaggio decriptato: " + Encoding.ASCII.GetString(msgDeCripted));



        }

        private void button10_Click(object sender, EventArgs e)
        {
            // Sono supportati 6 algoritmi nonkeyed (md5, ripemd160,sha...) e 2 keyed, il cui hash è criptato (HMCACSHA1 e MacTripleDES)
            MD5 myHash = new MD5CryptoServiceProvider();

            string fileToHash = @"c:\temp\testo_chiaro.txt";
            FileStream file = new FileStream(fileToHash, FileMode.Open, FileAccess.Read);
            
            BinaryReader reader = new BinaryReader(file);

            myHash.ComputeHash(reader.ReadBytes((int) file.Length));


            Console.WriteLine("Hash is " + Encoding.ASCII.GetString(myHash.Hash));
            Console.WriteLine("Hash is " + Convert.ToBase64String(myHash.Hash));


            reader.Close();
            file.Close();


        }

        private void button11_Click(object sender, EventArgs e)
        {
            // Iniziamo con la classe Assembly che e' piena di metodi statici

            // Ricavo l'assembly del codice in esecuzione
            Assembly theAssembly = Assembly.GetExecutingAssembly();

            FileStream[] fs = theAssembly.GetFiles();
            Module[] mod = theAssembly.GetModules();
            Type[] tp = theAssembly.GetTypes();

            // Leggo tutti gli attributi del  mio assembly
            object[] attrs = theAssembly.GetCustomAttributes(false);

            foreach (Attribute attribute in attrs)
                Console.WriteLine("Attributo Executing: " + attribute.GetType().Name);

            // leggo un attributo particolare
            Type attributoCopyright = typeof (AssemblyCopyrightAttribute);

            object[] copyrightAttrs = theAssembly.GetCustomAttributes(attributoCopyright, false);

            if (copyrightAttrs.Length > 0)
            {
                AssemblyCopyrightAttribute desc = (AssemblyCopyrightAttribute)copyrightAttrs[0];
                Console.WriteLine("Attributo trovato: " + desc.Copyright);

                

            }


            // Ricavo l'assembly di chi ha chiamato il codice in esecuzione
            //theAssembly = Assembly.GetCallingAssembly();

            //fs = theAssembly.GetFiles();
            //mod = theAssembly.GetModules();
            //tp = theAssembly.GetTypes();

            // Ricavo l'assembly di una dll del framework
            string fullName = "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";

            //theAssembly = Assembly.ReflectionOnlyLoad(fullName);

            theAssembly = Assembly.Load(fullName);

            // Reperisco tutti i files, moduli e tipi

            fs = theAssembly.GetFiles();
            mod = theAssembly.GetModules();
            //tp = theAssembly.GetTypes();

            if (mod.Length > 0)
            {

                // MethodInfo[] allMethods =  mod[0].GetMethods();
                string modulo = mod[0].FullyQualifiedName;

            }

            // Mi leggo tutti gli attributi dell'assembly

            attrs = theAssembly.GetCustomAttributes(false);

            foreach (Attribute attribute in attrs)
            {
                Console.WriteLine("Attributo Forms: " + attribute.GetType().Name);
            }



        }

        private void button12_Click(object sender, EventArgs e)
        {
            // Uso come test una mia class library
            string theAssembly = @"D:\_Svil\vb2008\StudySerialization\StudyReflection\bin\Debug\StudyReflection.dll";

            Assembly assembly = Assembly.LoadFrom(theAssembly);


            // Leggo tutti gli attributi del  mio assembly e visualizzo il tipo

            object[] attrs = assembly.GetCustomAttributes(false);


            foreach (Attribute thisAttr in attrs)
            {
                Console.WriteLine("Attributo: " + thisAttr.GetType().Name);

            }

            MethodInfo[] methods = typeof(Assembly).GetMethods();

            foreach (MethodInfo thisMethod in methods)
            {
                Console.WriteLine("Metodo: " + thisMethod.Name);

            }

            // E ora cerchiamo di arrivare a un metodo specifico
            string ilMioTipo = "StudyReflection.myClass";
            string ilMioMetodo = "myMethod";

            // Troviamo la classe
            Type myType = assembly.GetType(ilMioTipo, true, true);

            // Troviamo i metodi per quella classe
            MethodInfo[] myMethodss = myType.GetMethods();

            foreach (var info in myMethodss)
            {
                Console.WriteLine("Metodo: " + info.Name);
            }

            // E ora cerchiamo un metodo specifico
            MethodInfo myMethod = myType.GetMethod(ilMioMetodo);

            // E ora cerchiamo di lanciarlo!!!
            object instance = Activator.CreateInstance(myType);

            // Questo metodo vuole 2 argomenti (int)? eccoli
            Object[] myArgs = new Object[2] {4, 5};

            // Invoco il metodo tramite refleciton
            object ret = myMethod.Invoke(instance, myArgs);

            // Faccio il parsing del risultato e lo mostro, incredibile
            Console.WriteLine("Il risultato del metodo scoperto tramite reflection è: " + (int) ret);


        }

        private void button13_Click(object sender, EventArgs e)
        {
            // Uso come test una mia class library
            //string theAssembly = @"D:\_Svil\vb2008\StudySerialization\StudyReflection\bin\Debug\StudyReflection.dll";
            string theAssemblyHome = @"E:\Svil\rep-vb2008\StudyReflection\bin\Debug\StudyReflection.dll";

            // Mi carico l'assembly
            Assembly assembly = Assembly.LoadFrom(theAssemblyHome);

            // Ricavo i moduli, tanto è solo uno
            Module[] modules = assembly.GetModules();

            // Ricavo i tipi (classi) del modulo che mi interessa: "StudyReflection.myClass"
            Type type = modules[0].GetType("StudyReflection.myClass");

            Console.WriteLine("Il tipo è una classe? " + type.IsClass);
            Console.WriteLine("La classe è pubblica? " + type.IsPublic);

            // Ottengo tutti i campi (es _myClassVar, myVar, mioENum )
            FieldInfo[] fields = type.GetFields();

            // Ottengo tutte le proprietà (myProp)
            PropertyInfo[] properties = type.GetProperties();

            // Ottengo tutti i nested come gli enum (myEnum)
            Type[] types = type.GetNestedTypes();

            BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;

            // E con questa ottengo tutto insieme o solo quello che mi serve
            MemberInfo[] members = type.GetMembers(flags);

            foreach (MemberInfo info in members)
            {
                if (info.MemberType == MemberTypes.Constructor)
                {
                    ConstructorInfo constructorInfo = (ConstructorInfo) info;
                    Console.WriteLine("{0} è un construttore!" , info.Name);
                }
                if (info.MemberType == MemberTypes.Event)
                {
                    EventInfo eventInfo = (EventInfo)info;
                    Console.WriteLine("{0} è un event!", info.Name);
                }
                if (info.MemberType == MemberTypes.Field)
                {
                    FieldInfo eventInfo = (FieldInfo)info;
                    Console.WriteLine("{0} è un field!", info.Name);
                    Console.WriteLine("- di tipo: " + eventInfo.FieldType.ToString());
                }
                if (info.MemberType == MemberTypes.Method)
                {
                    MethodInfo eventInfo = (MethodInfo)info;
                    Console.WriteLine("{0} è un method!", info.Name);
                    Console.WriteLine("- parametro di ritorno: " + eventInfo.ReturnType.Name);

                }
                if (info.MemberType == MemberTypes.NestedType)
                {
                    MemberInfo eventInfo = (MemberInfo)info;
                    Console.WriteLine("{0} è un Nested!", info.Name);
                }
                if (info.MemberType == MemberTypes.Property)
                {
                    PropertyInfo eventInfo = (PropertyInfo)info;
                    Console.WriteLine("{0} è una Property!", info.Name);
                    Console.WriteLine("- proprieta' di tipo: " + eventInfo.PropertyType.Name);
                }
                if (info.MemberType == MemberTypes.TypeInfo)
                {
                    Type eventInfo = (Type)info;
                    Console.WriteLine("{0} è un Type!", info.Name);
                }

            }

            // E ora, dinamicamente, grazie alla reflection istanziamo il tipo (classe)
            // e successivamente richiamerermo il metodo myPublicMethod 
            // e visualizzeremo il field myVar

            // Il tipo ce l'ho, ricavo il costructor con nessun parametro
            Type[] tipiConstructor = Type.EmptyTypes;
            //Type[] tipiConstructor = new Type[] { typeof(string) };
            ConstructorInfo ctor = type.GetConstructor(tipiConstructor);
            
            // Ora che ho il construcotr, posso istanziare la mia classe
            object reflMyClass = ctor.Invoke(null);

            // Ora che la classe e' istanziata posso richiamare il mio metodo

            MethodInfo reflMyPublicMethod = type.GetMethod("myPublicMethod");
            object ret = reflMyPublicMethod.Invoke(reflMyClass, new object[] {30, 44});

            Console.WriteLine("La somma ha dato: " + (int)ret);

            // Quanto vale myvar? è un field
            FieldInfo reflMyVar = type.GetField("myVar");
            ret = reflMyVar.GetValue(reflMyClass);


            Console.WriteLine("MyVar vale: " + (int)ret);


        }

        private void button14_Click(object sender, EventArgs e)
        {

            // Classe VB6 (dll ActiveX) caricata tramite InterOperation
            Project1.Class1Class interopClass = new Class1Class();

            // Assegno variabili
            String name = "Pippo";
            String last = "De Pipponi";

            // Eseguo metodi
            interopClass.set_Firstname(ref name);
            interopClass.set_Lastname(ref last);

            Console.WriteLine("Interop ha detto: {0} {1}", interopClass.get_Firstname().ToString(),
                              interopClass.get_Lastname().ToString());

            // Prova con COM di iTunes
            iTunesAppClass itunes = new iTunesAppClass();

            Console.WriteLine("Versione iTunes: " + itunes.Version.ToString());

            IITTrack track = itunes.CurrentTrack;

            // Gestione eccezione

            try
            {
                string trackName = track.Name;
            }
            catch (Exception ex)
            {
                
                Console.WriteLine("Eccezione: " + ex.Message);
                //return;
            }

            if (itunes.PlayerState == ITPlayerState.ITPlayerStatePlaying )
            {
                Console.WriteLine("Canzone in corso: " + track.Name);
                itunes.Stop();
            }
            else
                Console.WriteLine("Player stoppato");


        }

        private void button15_Click(object sender, EventArgs e)
        {
            StringCollection stringCollection = new StringCollection();

            stringCollection.Add("stringa1");
            stringCollection.Add("stringa2");

            Console.WriteLine("cont: " + stringCollection.Count);

            int pos = stringCollection.IndexOf("stringa2");

            Console.WriteLine("posizione:  " + pos);


        }
    }
}
